﻿Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.ComponentModel.Design.Serialization
Imports System.Workflow.ComponentModel.Compiler
Imports System.Xml

Namespace System.Workflow.ComponentModel.Serialization
    <DesignerSerializer(GetType(TypeExtensionSerializer), GetType(WorkflowMarkupSerializer))> _
    Friend NotInheritable Class TypeExtension
        Inherits MarkupExtension
        ' Methods
        Public Sub New()
        End Sub

        Public Sub New(ByVal type As String)
            If (type Is Nothing) Then
                Throw New ArgumentNullException("typeName")
            End If
            Me.typeName = type
        End Sub

        Public Sub New(ByVal type As Type)
            If (type Is Nothing) Then
                Throw New ArgumentNullException("type")
            End If
            Me.type = type
        End Sub

        Public Overrides Function ProvideValue(ByVal provider As IServiceProvider) As Object
            If (Not Me.type Is Nothing) Then
                Return Me.type
            End If
            If (provider Is Nothing) Then
                Throw New ArgumentNullException("provider")
            End If
            If (Me.typeName Is Nothing) Then
                Throw New InvalidOperationException("typename")
            End If
            Dim manager As WorkflowMarkupSerializationManager = [TryCast](provider,WorkflowMarkupSerializationManager)
            If (manager Is Nothing) Then
                Throw New ArgumentNullException("provider")
            End If
            Dim reader As XmlReader = [TryCast](manager.WorkflowMarkupStack.Item(GetType(XmlReader)),XmlReader)
            If (Not reader Is Nothing) Then
                Dim name As String = Me.typeName.Trim
                Dim prefix As String = String.Empty
                Dim index As Integer = name.IndexOf(":"c)
                If (index >= 0) Then
                    prefix = name.Substring(0, index)
                    name = name.Substring((index + 1))
                    Me.type = manager.GetType(New XmlQualifiedName(name, reader.LookupNamespace(prefix)))
                    If (Not Me.type Is Nothing) Then
                        Return Me.type
                    End If
                    Dim list As List([Of] WorkflowMarkupSerializerMapping) = Nothing
                    If ((manager.XmlNamespaceBasedMappings.TryGetValue(reader.LookupNamespace(prefix), list) AndAlso (Not list Is Nothing)) AndAlso (list.Count > 0)) Then
                        Return (list.Item(0).ClrNamespace & "." & name)
                    End If
                    Return name
                End If
                Me.type = manager.GetType(New XmlQualifiedName(name, reader.LookupNamespace(String.Empty)))
                If (Me.type Is Nothing) Then
                    Dim service As ITypeProvider = [TryCast](provider.GetService(GetType(ITypeProvider)),ITypeProvider)
                    If (Not service Is Nothing) Then
                        Me.type = service.GetType(name)
                    End If
                    If ((Me.type Is Nothing) AndAlso (manager.GetService(GetType(ITypeResolutionService)) Is Nothing)) Then
                        Me.type = manager.SerializationManager.GetType(name)
                    End If
                End If
                If (Not Me.type Is Nothing) Then
                    Return Me.type
                End If
            End If
            Return Me.typeName
        End Function


        ' Properties
        Friend ReadOnly Property Type As Type
            Get
                Return Me.type
            End Get
        End Property

        <DefaultValue(CStr(Nothing)), ConstructorArgument("type")> _
        Public Property TypeName As String
            Get
                If (Not Me.type Is Nothing) Then
                    Return Me.type.FullName
                End If
                Return Me.typeName
            End Get
            Set(ByVal value As String)
                If (value Is Nothing) Then
                    Throw New ArgumentNullException("value")
                End If
                Me.typeName = value
            End Set
        End Property


        ' Fields
        Private type As Type
        Private typeName As String
    End Class
End Namespace

